home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / manage / snmp / kip / rtmp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-01-17  |  18.3 KB  |  816 lines

  1. /*
  2.  * RTMP / ZIP etc.
  3.  *
  4.  * (c) 1986, Stanford Univ. CSLI.
  5.  * May be used but not sold without permission.
  6.  *
  7.  * $Header: rtmp.c,v 4.1 88/11/01 19:51:00 sw0l Locked $
  8.  */
  9.  
  10. #include "gw.h"
  11. #include "gwctl.h"
  12. #include "fp/pbuf.h"
  13. #include "ab.h"
  14. #include "inet.h"
  15. #include "fp/cmdmacro.h"
  16.  
  17. #include "glob.h"
  18. extern u_char broadcastaddr[];
  19.  
  20. #ifdef SNMP
  21. #include "mib.h"
  22. #include "snmp_vars.h"
  23. #endif
  24.  
  25.  
  26. short rtmp_delay, rtmp_vdelay;        /* 'static' */
  27.  
  28. short    art_delay;        /* 'static' */
  29. short zip_delay;
  30. struct aroute *notzipped;
  31. struct aroute *art_last;    /* 'static', last aroute pointer */
  32.  
  33. /*
  34.  * RTMP clock routine.  
  35.  * Broadcasts RTMP's on AppleTalk segment, age routes.
  36.  */
  37. rtmptimer()
  38. {
  39.     register struct aroute *ar;
  40.     int i;
  41.  
  42.     if (rtmp_delay && ++rtmp_delay < 11)
  43.         return;    /* run only every 10 seconds */
  44.  
  45.     rtmp_delay = 1;
  46.  
  47.     /* broadcast the current routing table on appletype interfaces */
  48.     for (i = 0 ; i < MAX_PORT; i++)
  49.       if (porttoif[i] && porttoif[i]->if_flags & IF_APPLETYPE)
  50.         rtmpsend(porttoif[i]);
  51.  
  52.     if (rtmp_vdelay++ == 0)    /* validity timer goes off every 20 secs */
  53.         return;
  54.     rtmp_vdelay = 0;
  55.     /* age routes in our table */
  56.     for (ar = &aroute[0] ; ar < &aroute[NAROUTE] ; ++ar) {
  57.         if (ar->net == 0 || ar->hops == 0 || (ar->flags & arouteAA))
  58.             continue;
  59.         if (arouteBad(ar)) {
  60.             ar->net = 0;    /* delete it */
  61.             continue;
  62.         }
  63.         if (ar->age < 255)
  64.             ar->age++;
  65.     }
  66. }
  67.  
  68.  
  69. /*
  70.  * Send an RTMP packet.  If 'tuples' is true, 
  71.  * include the routing tuples.
  72.  */
  73. /* break into send and reply */
  74.  
  75. /* rtmp send: used only to broadcast rtmp "here I ams" */
  76. /* setup for ddp reply and call rtmpreply */
  77. rtmpsend(ifp)
  78.      struct ifnet *ifp;
  79. {
  80.   source_if = ifp;
  81.   ddp.srcNet = source_if->if_dnet;
  82.   ddp.srcNode = 0xff;        /* broadcast */
  83.   ddp.srcSkt = rtmpSkt;
  84.   rtmpreply(1);
  85. }
  86.  
  87. /* rtmp reply - reply to last packet (was rtmp request) */
  88. rtmpreply(tuples)
  89. {
  90.     register struct pbuf *p;
  91.     register struct RTMP *r;
  92.     register i;
  93.  
  94.     K_PGET(PT_DATA, p);
  95.     if (p == 0)
  96.         return;
  97.     r = (struct RTMP *)(p->p_off + lapSize + ddpSize);
  98.     r->net = source_if->if_dnet;
  99.     r->idLen = 8;
  100.     r->id = source_if->if_dnode;
  101.     if (tuples)
  102.         i = rtmpsettuples((caddr_t)(r + 1));
  103.     else
  104.         i = 0;
  105.     /* setup for ddp send */
  106.     ddp.type = ddpRTMP;    /* in case request */
  107.     p->p_len = i+rtmpSize+ddpSize+lapSize;
  108.     ddpreply(p, rtmpSkt);
  109. }
  110.  
  111.  
  112. /*
  113.  * Merge new routing tuples into our aroute table.
  114.  */
  115. rtmpmerge(cp, count, sender)
  116.     register unsigned char *cp; /* start of tuple array [3][n] */
  117.     int count;        /* count of tuples */
  118.     int sender;        /* node of tuple sender */
  119. {
  120.   struct arouteTuple at;
  121.   int port;
  122.  
  123.   at.node = sender;
  124.   port = source_if->if_unit;
  125.   for ( ; count > 0 ; count--) {
  126.     at.net = (*cp)<<8|(*(cp+1));
  127.     at.hops = *(cp+2);
  128.     at.flags = 0;
  129.     cp+=3;            /* advance */
  130.     newroute(&at, port);
  131.   }
  132. }
  133.  
  134. newroute(at, port)
  135. register struct arouteTuple *at;
  136. int port;
  137. {
  138.   struct aroute *arfree = 0;
  139.   register struct aroute *ar;
  140.  
  141.   for (ar = &aroute[0] ; ar < &aroute[NAROUTE] ; ++ar) {
  142.     if (ar->net == 0) { /* remember a free slot */
  143.       if (arfree == 0) arfree = ar;
  144.       continue;
  145.     }
  146.     if (at->net == ar->net) {
  147.       /* search for this tuple net in table */
  148.       /* [want check inside so we drop the extra aaroutes] */
  149.       if (ar->hops == 0)        /* never touch local entries */
  150.     return;
  151.       if (arouteBad(ar) && at->hops < 15)
  152.     goto replace;
  153.       if (ar->hops >= (at->hops+1) && at->hops < 15)
  154.     goto replace;
  155.       if (ar->node == at->node && port == ar->port) {
  156.     if ((ar->hops = at->hops + 1) < 16)
  157.       ar->age = 0;
  158.     else
  159.       ar->net = 0;
  160.       }
  161.       return;
  162.     }
  163.   }
  164. /* add */
  165.     /* tuple net # wasnt in our table, add it */
  166.     if ((ar = arfree) == 0)
  167.       return;            /* oops, out of room */
  168.     arfree = 0;
  169.   /* until we implment zip takedown, bringup, it's probably best to */
  170.   /* to put zone setting in "replace", but .... */
  171.     ar->zone = 0;
  172.     if (!notzipped)
  173.       notzipped = ar;
  174. replace:
  175.     ar->net = at->net;
  176.     ar->hops = at->hops + 1;
  177.     ar->node = at->node;
  178.     ar->port = port;
  179.     ar->age = 0;
  180.     ar->flags = at->flags;
  181. }
  182.  
  183.  
  184. /*
  185.  * Setup a tuple array, starting at cp;  returns total size 
  186.  * of the array in bytes.
  187.  */
  188. rtmpsettuples(cp)
  189.     register char *cp;
  190. {
  191.     register count;
  192.     register struct aroute *ar;
  193.  
  194.     count = 0;
  195.     for (ar = &aroute[0] ; ar < &aroute[NAROUTE] ; ++ar) {
  196.         if (ar->net == 0 || arouteBad(ar))
  197.             continue;
  198.         if (ar->zone == 0 && notzipped == 0)
  199.           notzipped = ar;
  200.         /* copy in the net, hops, but be careful of byte aligment */
  201.         *cp++ = ar->net >> 8;
  202.         *cp++ = ar->net & 0xff;
  203.         *cp++ = ar->hops;
  204.         count += 3;
  205.     }
  206.     return (count);
  207. }
  208.  
  209.  
  210. /*
  211.  * RTMP received from AppleTalk.
  212.  */
  213. rtmpinput(p)
  214.     struct pbuf *p;
  215. {
  216.   register struct RTMP *r;
  217.   register tbytes, tuples;
  218.   int src;
  219.  
  220.   p->p_len -= (lapSize+ddpSize); /* skip lap+ddp */
  221.   p->p_off += (lapSize+ddpSize);
  222.     
  223.   /* rtmp from ourselfs */
  224.   if ((ddp.dstNet == source_if->if_dnet && ddp.dstNode==source_if->if_dnode) ||
  225.       p->p_len < 1)
  226.     goto drop;
  227.  
  228.   if (ddp.type == ddpRTMPR) {
  229.     /* RTMP request from Mac trying to get his net # */
  230.     if (*p->p_off != 1)
  231.       goto drop;    /* only opcode defined now is 1 */
  232.     rtmpreply(0);    /* reply */
  233.     goto drop;
  234.   }
  235.  
  236.   r = (struct RTMP *)p->p_off;
  237.   src = r->id;
  238.   if (p->p_len < sizeof(struct RTMP) ||
  239.       (tbytes = ddp.length-ddpSize-sizeof(struct RTMP)) <= 0 ||
  240.       r->idLen != 8 || r->id == source_if->if_dnode)
  241.     goto drop;
  242.  
  243.   if ((tuples = tbytes/3)) /* if we have any tuples, merge them in */
  244.     rtmpmerge((caddr_t)(r+1), tuples, src);
  245. drop:
  246.   K_PFREE(p);
  247. }
  248.  
  249.  
  250. /*
  251.  * Send arouteTuple's to gateway at 'ia'.
  252.  * If 'all' flag is true, sends all routes not configured by AA.
  253.  * If 'all' is 0, only sends locally discovered routes (new atalk
  254.  * segments dynamically plugged in).
  255.  */
  256. artsend(ia, all)
  257.     iaddr_t ia;
  258.     register all;
  259. {
  260.     register struct aroute *ar;
  261.     register struct arouteTuple *at;
  262.     struct pbuf *p;
  263.     register count;
  264.  
  265.     count = 0;
  266.     K_PGET(PT_DATA, p);
  267.     if (p == 0)
  268.         return(0);
  269.     at = (struct arouteTuple *)m_stuff(p->p_off);
  270.     for (ar = &aroute[0] ; ar < &aroute[NAROUTE] ; ++ar) {
  271.         if (ar->net == 0 || ar->hops == 0)
  272.             continue;    /* skip null & local entries */
  273.         if (all) {
  274.             if (ar->flags & arouteAA)
  275.                 continue;    /* skip AA entries */
  276.         } else {
  277.             if (arouteIP(ar))
  278.                 continue;    /* skip IP entries */
  279.         }
  280.  
  281.         if (arouteIP(ar)) {
  282.             at->node = ar->node;
  283.             at->flags = ar->flags;
  284.         } else {
  285.             /* if node was an atalk address, subst. our IP addr */
  286.             at->node = conf.ipaddr;
  287.             at->flags = arouteKbox;
  288.         }
  289.         at->net = ar->net;
  290.         at->hops = ar->hops;
  291.         at++;
  292.         count++;
  293.     }
  294.     if (count == 0 && all)
  295.         goto drop;    /* dont sent null aaROUTE packets */
  296.     kipit(p, ia, all ? aaROUTE : aaROUTEQ, count * sizeof *at);
  297.     /* (but we would send a null aaROUTEQ query packet) */
  298.     return (1);
  299. drop:
  300.     K_PFREE(p);
  301.     return (0);
  302. }
  303.  
  304.  
  305. /*
  306.  * arouteTuple timer routine.  Once per minute send arouteTuple's
  307.  * to 'core' gateways.
  308.  */
  309. arttimer()
  310. {
  311.     register struct aroute *ar;
  312.     register count;
  313.  
  314.     if (art_delay && ++art_delay < 60)
  315.         return;    /* run only every 60 seconds */
  316.     art_delay = 1;
  317.     if (arouteinit == 0) {
  318.         /* if routes not yet received from AA */
  319.         confrequest(aaROUTEI);
  320.     }
  321.     /*
  322.      * send local additions to one of the core's,
  323.      * chosen circularly.
  324.      */
  325.     if ((ar = art_last) == 0)
  326.         ar = &aroute[0];
  327.     for (count = 0 ; count < NAROUTE ; count++) {
  328.         ar++;
  329.         if (ar >= &aroute[NAROUTE])
  330.             ar = &aroute[0];
  331.         if (ar->net == 0 || (ar->flags & arouteCore) == 0)
  332.             continue;
  333.         art_last = ar;
  334.         artsend(ar->node, 0);
  335.         return;
  336.     }
  337.     /* else no core gateways found */
  338.     return;
  339. }
  340.  
  341.  
  342. /*
  343.  * arouteTuples received from another gateway or AA.
  344.  * Merge into our table and send reply if requested.
  345.  */
  346. artinput(aa, ipsrc)
  347.     register struct aaconf *aa;
  348.     iaddr_t ipsrc;
  349. {
  350.   register struct arouteTuple *at;
  351.   register struct aroute *ar;
  352.   register count, type;
  353.  
  354.   if ((type = aa->type) == aaROUTEI) {
  355.     /* if init table from AA, clear all entries */
  356.     for (ar = &aroute[0] ; ar < &aroute[NAROUTE] ; ++ar)
  357.       if (ar->flags & arouteAA)
  358.     ar->net = 0;
  359.   }
  360.   at = (struct arouteTuple *)aa->stuff;
  361.   for (count = aa->count / sizeof *at ; count > 0 ; count--, at++) {
  362.     if (type == aaROUTEI)
  363.       at->flags |= arouteAA;
  364.     newroute(at, 1);        /* 1 is the ip port */
  365.   }
  366.   if (type == aaROUTEQ)
  367.     artsend(ipsrc, 1);
  368.   else if (type == aaROUTEI) {
  369.     artsend(ipsrc, 0);
  370.     arouteinit = 1;
  371.   }
  372. }
  373.  
  374.  
  375. /*
  376.  * Get the aroute entry corresponding to the atalk net number
  377.  * supplied.  Returns 0 if not routed via LocalTalk, otherwise the bridge's
  378.  * node number on our atalk segment (or -1 if local segment).
  379.  */
  380. getaroute(net)
  381.     register net;
  382. {
  383.   register struct aroute *ar;
  384.  
  385.   for (ar = &aroute[0] ; ar < &aroute[NAROUTE] ; ++ar) {
  386.     if (ar->net == 0 || ar->net != net)    /* empty slot */
  387.       continue;
  388.     /* not a LocalTalk port or invalid port */
  389.     /* if (ar->port > MAX_PORT) return(0); - paranoia */
  390.     if (!porttoif[ar->port] || (porttoif[ar->port]->if_flags & IF_ALAP) == 0)
  391.       return(0);
  392.     return(ar->node ? ar->node : -1);
  393.   }
  394.   return (0);
  395. }
  396.  
  397.  
  398. /*
  399.  * Ziptimer;  gets aaZONE table from AA.  Perhaps should
  400.  * also zipQuery unzoned nets...
  401.  */
  402. ziptimer()
  403. {
  404.   if (arouteinit == 0)
  405.     return;        /* wait until routing table received */
  406. #ifdef notdef
  407.   if (azoneinit == 0) {    /* if aaZONE not yet received */
  408.     confrequest(aaZONE);
  409.     return;
  410.   }
  411. #endif
  412.  
  413.   if (notzipped == 0 || (zip_delay && ++zip_delay < 5)) /* once every 5 sec*/
  414.     return;
  415.   zip_delay = 1;
  416.  
  417.   zipquery();
  418. }
  419.  
  420. zipquery()
  421. {
  422.   struct pbuf *p;
  423.   register struct aroute *ar;
  424.   struct ZIP *z;
  425.   u_short *n;
  426.   int count;
  427.   u_char port;
  428.   long node;
  429.   int toadmin = 0;
  430.  
  431.   if (notzipped == 0)
  432.     return;
  433.   if (notzipped->zone) {
  434.     notzipped = 0;
  435.     return;
  436.   }
  437.   K_PGET(PT_DATA, p);
  438.   if (p == 0)
  439.     return;
  440.   port = notzipped->port;
  441.   node = notzipped->node;
  442.   /* necessary to fake ddp reply */
  443.   source_if = porttoif[notzipped->port];
  444.   if (source_if->if_flags & IF_IPUDP) {
  445.     toadmin = (notzipped->flags & arouteAA) || notzipped->hops == 0 ;
  446.     z = (struct ZIP *)m_stuff(p->p_off);
  447.     count = sizeof(struct ZIP);
  448.   } else {
  449.     /* pretend replying to bridge that advertised this rtmp */
  450.     ddp.srcNet = source_if->if_dnet;
  451.     ddp.srcNode = notzipped->node;
  452.     ddp.srcSkt = zipSkt;
  453.     ddp.type = ddpZIP;
  454.     count = sizeof(struct ZIP);
  455.     z = (struct ZIP *)(p->p_off + lapSize + ddpSize);
  456.   }
  457.   z->command = zipQuery;
  458.   z->count = 0;
  459.   n = (u_short *)(z+1);    /* point to start of nets */
  460.   notzipped = 0;
  461.   for (ar = &aroute[0] ; ar < &aroute[NAROUTE]; ++ar) {
  462.     if (ar->net && ar->zone == 0) {
  463.       if (!toadmin) {
  464.     if (ar->node != node || ar->port != port) {
  465.       if (!notzipped)        /* if no new selection */
  466.         notzipped = ar;    /* try one! */
  467.       continue;
  468.     }
  469.       } else if ((ar->flags & arouteAA) == 0 && ar->hops != 0)
  470.     continue;
  471.       *n = ar->net;
  472.       n++;
  473.       z->count++;
  474.       count +=2;
  475.     }
  476.   }
  477.   if (source_if->if_flags & IF_IPUDP) {
  478.     kipit(p, toadmin ? conf.ipadmin : node, aaZONEQ, count);
  479.   } else {
  480.     p->p_len = lapSize+ddpSize+count;
  481.     ddpreply(p, zipSkt);
  482.   }
  483. }
  484.  
  485.  
  486. u_char *azonep;
  487. int numzones;
  488.  
  489. newzone(s)
  490. u_char *s;
  491. {
  492.   u_char i;
  493.   int zi;
  494.  
  495.   if (azonep == 0)
  496.     azonep = azonenames;
  497.   if ((zi=zipfind(s, 0)) > 0)
  498.     return(zi);
  499.   if (numzones >= (NAZONE-2))    /* no more room */
  500.     return(0);
  501.   i = *s++;            /* get the length */
  502.   if ((i + azonep + 2) > (azonenames+sizeof(azonenames))) /* check it */
  503.     return(0);
  504.   azone[++numzones] = azonep;    /* set dp */
  505.   azone[numzones+1] = 0;    /* tie off end */
  506.   *azonep++ = i;
  507.   /* Check for special zone that gets all requests */
  508.   if (strncmp(s, ALLZONES, i) == 0)
  509.     allzones = numzones;
  510.   bcopy(s, azonep, i);
  511.   azonep += i;
  512.   return(numzones);        /* return index */
  513. }
  514.  
  515. #ifdef notdef
  516. /*
  517.  * Called from ip4me() when aaZONE arrives from AA.
  518.  * Setup our zone table and zone indexes in aroute.
  519.  */
  520. zipinit(aa)
  521.     struct aaconf *aa;
  522. {
  523.   register u_char *cp,*ncp;
  524.   register i,l,iz;
  525.   register unsigned n;
  526.  
  527.   
  528.   /*
  529.    * parse aaZONE table; format:
  530.    * net# net# ... 0 zonename
  531.    * net# net# ... 0 zonename
  532.    * 0xFFFF
  533.    */
  534.   for (cp = aa->stuff;;) {
  535.     ncp = cp;
  536.     do {
  537.       n = *cp++;
  538.       n <<= 8;
  539.       n |= *cp++;
  540.     } while (n && n != 0xffff);
  541.     if (n == 0xFFFF)
  542.       break;            /* end of table */
  543.     l = *cp;            /* length of str */
  544.     iz = newzone(cp);
  545.     if (iz == 0)        /* no more room */
  546.       break;
  547.     /* Check for special zone that gets all requests */
  548.     if (strncmp(cp+1, ALLZONES, l) == 0)
  549.       allzones = iz;
  550.     do {
  551.       n = *ncp++;
  552.       n <<= 8;
  553.       n |= *ncp++;
  554.       if (n == 0)
  555.     break;
  556.       for (i = 0 ; i < NAROUTE ; ++i)
  557.     if (n == aroute[i].net)
  558.       break;
  559.       if (i < NAROUTE)
  560.     aroute[i].zone = iz;
  561.     } while (n);
  562.     cp += l + 1;
  563.   }
  564.   /* end of table */
  565.   azone[0] = azone[aroute[0].zone];    /* my own zone */
  566.   azoneinit = 1;    /* dont ask for aaZONE anymore */
  567. }
  568. #endif
  569.  
  570. /*
  571.  * Find the zone index, given the name;  returns -1 if not found.
  572.  * set flag true if want (conf.flags).
  573.  */
  574. zipfind(s, flag)
  575.     register u_char *s;
  576.     int flag;
  577. {
  578.     register i;
  579.  
  580.     for (i = 1 ; ; i++) {
  581.         if (azone[i] == 0)
  582.             return (-1);    /* reached end of table */
  583.         if (*azone[i] != *s) /* lengths must match */
  584.           continue;
  585.         if (strncmpci(s+1, azone[i]+1, *s) != 0)
  586.             continue;
  587.         if (flag && (conf.flags & conf_stayinzone))
  588.           if (aroute[0].zone && azone[i] != azone[aroute[0].zone])
  589.             return (-1);
  590.         return (i);
  591.     }
  592. }
  593.  
  594. /* 
  595.  * String compare, case independent;
  596.  * returns zero if equal, one otherwise
  597.  */
  598. strncmpci(s,t,n)
  599. char *s,*t;
  600. int n;
  601. {
  602.   register char c,d;
  603.  
  604.   while (n--) {
  605.     c = *s++;
  606.     if (c >= 'A' && c <= 'Z')
  607.       c += ('a'-'A');        /* convert to lower case */
  608.     d = *t++;
  609.     if (d >= 'A' && d <= 'Z')
  610.       d += ('a'-'A');        /* convert to lower case */
  611.     if (c != d)
  612.       return(1);
  613.     if (c == '\0')
  614.       return(0);
  615.   }
  616.   return(0);            /* success on runnout */
  617. }
  618.  
  619.  
  620. /*
  621.  * Process ZIP packet received on input.
  622.  */
  623. zipatp(ip)
  624. struct pbuf *ip;
  625. {
  626.   union zipatp {
  627.     struct ATP a;        /* atp */
  628.     u_char c[sizeof(struct ATP)]; /* 8 bytes */
  629.     u_short s[sizeof(struct ATP)/sizeof(u_short)]; /* 4 words */
  630.   } zipatp, *zap;
  631.   u_char *po, *pi;
  632.   int zl;            /* zone length */
  633.   int zi;            /* zone index */
  634.   int fzones;            /* # of found zones */
  635.   int len, count, i,j ;
  636.   register struct aroute *ar;
  637.  
  638.   /* we can reuse the input packet (query needs too much out of it) */
  639. #define GMZ 7            /* get my zone */
  640. #define GZL 8            /* get zone list */
  641.   /* big enough? */
  642.   if (ip->p_len < (lapSize+ddpSize+sizeof(struct ATP)))
  643.     goto drop;
  644.   po = ip->p_off + lapSize + ddpSize;
  645.   bcopy(po, &zipatp, sizeof(zipatp));
  646.   if (zipatp.a.control != atpReqCode ||
  647.       (zipatp.a.bitmap & 0x1) == 0 || /* at least 1 packet */
  648.       (zipatp.c[4] != GMZ && zipatp.c[4] != GZL) ||
  649.       zipatp.c[5] != 0)
  650.     goto drop;
  651.   zap = (union zipatp *)po;
  652.   po += sizeof(zipatp);        /* move ahead */
  653.   zap->a.control = atpRspCode|atpEOM; /*rsp+EOM */
  654.   zap->a.bitmap = 0;        /* set seq to match bitmap */
  655.   /* tid already set */
  656.   len = 0;
  657.   switch (zipatp.c[4]) {
  658.   case GMZ:
  659.     zap->c[4] = 0;
  660.     /* Find the zone for the interface request came in on */
  661.     /* cck: modify to find the zone for the source network */
  662.     /* of the packet that came in */
  663.     for (ar = &aroute[0]; ar < &aroute[NAROUTE]; ++ar)
  664.       if (ar->net == ddp.srcNet)
  665.     break;
  666.     if (ar == &aroute[NAROUTE] || ar->zone == 0)
  667.       goto drop;
  668.     pi = azone[ar->zone];
  669.     zl = *pi + 1;
  670.     bcopy(pi, po, zl);        /* get zone */
  671.     len += zl;            /* and move ptr */
  672.     zap->s[3] = 1;        /* set count */
  673.     break;
  674.   case GZL:
  675.     if (conf.flags & conf_stayinzone)
  676.       break;
  677.     /* not clear which bit "lastflag" is */
  678.     zap->c[4] = 0xff;
  679.     /* first index is 1 */
  680.     for (fzones = 0, zi=zipatp.s[3]; azone[zi] ; ++zi) {
  681.       if (zi == allzones)
  682.     continue;
  683.       pi = azone[zi];
  684.       zl = *pi + 1;
  685.       /* enable this if azone is defined larger than atpMaxData */
  686.       if (len + zl > 512) {    /* less than maxsize */
  687.     zap->c[4] = 0;        /* clear lastflag */
  688.     break;
  689.       }
  690.       bcopy(pi, po, zl);
  691.       fzones++;            /* increment count */
  692.       po += zl;
  693.       len += zl;
  694.     }
  695.     zap->s[3] = fzones;        /* set count */
  696.     break;
  697.   }
  698.   ip->p_len = lapSize+ddpSize+sizeof(zipatp)+len;
  699.   ddpreply(ip, zipSkt);
  700.   return;
  701.  drop:
  702.   K_PFREE(ip);
  703. }
  704.  
  705. zipinput(z, zlen,ia)
  706.      struct ZIP *z;
  707.      int zlen;
  708.      long ia;
  709. {
  710.   register u_char *pi, *po, *zn;
  711.   register struct aroute *ar;
  712.   register count, i, len;
  713.   int j;
  714.   u_short *sp;
  715.   struct pbuf *op;
  716.   union {
  717.     u_short s;
  718.     u_char c[2];
  719.   } u;
  720.  
  721.   zlen -= sizeof(struct ZIP);
  722.   if (zlen <= 0)        /* bad or empty */
  723.       return;
  724.   if (z->command == zipQuery)
  725.     goto query;
  726.   if (z->command == zipReply)
  727.     goto reply;
  728. #ifdef notdef
  729.   if (z->command == zipTakedown)
  730.     goto takedown;
  731. #endif
  732.   return;
  733. reply:
  734.   /* assume (ha) that length is right */
  735.   pi = (u_char *)(z+1);        /* point past header */
  736.   j = z->count;
  737.   while (j-- != 0) {
  738.     u.c[0] = *pi++;        /* network */
  739.     u.c[1] = *pi++;
  740.     zn = pi;            /* remeber zone name */
  741.     pi += ((*pi)+1);        /* skip past zone name */
  742.     for (ar = &aroute[0] ; ar < &aroute[NAROUTE]; ++ar) {
  743.       if (u.s != ar->net)
  744.     continue;
  745.       if (ar->zone == 0)
  746.     ar->zone = newzone(zn);
  747.       break;            /* break anyway since already zipped */
  748.     }
  749.  
  750.   }
  751.   return;
  752. query:
  753.   K_PGET(PT_DATA, op);
  754.   if (op == 0)
  755.     return;
  756.   j = z->count;
  757.   sp = (u_short *)(z+1);
  758.   /* setup output packet */
  759.   z = (struct ZIP *)(ia ? m_stuff(op->p_off) : (op->p_off + lapSize+ddpSize));
  760.   z->command = zipReply;
  761.   po = (u_char *)(z+1);
  762.   len = sizeof(struct ZIP);
  763.   for (count = 0; j && len < 512 ; j--) {
  764.     u.s = i = *sp++;        /* network */
  765.     for (ar = &aroute[0]; ar < &aroute[NAROUTE] ; ++ar) {
  766.       if (i == ar->net)
  767.     break;
  768.     }
  769.     if (ar >= &aroute[NAROUTE] || ar->zone == 0)
  770.       continue;            /* no match */
  771.     count++;            /* found one */
  772.     pi = azone[ar->zone];
  773.     *po++ = u.c[0];        /* copy in network */
  774.     *po++ = u.c[1];
  775.     bcopy(pi, po, *pi + 1);    /* copy in zone */
  776.     po += (*pi + 1);        /* string + count */
  777.     len += (*pi + 3);        /* string + count + netnumber */
  778.   }
  779.   z->count = count;
  780.   if (ia) {
  781.     kipit(op, ia, aaZONEQ, len);
  782.   } else {
  783.     op->p_len = lapSize + ddpSize + len;
  784.     ddpreply(op, zipSkt);
  785.   }
  786.   return;
  787. }
  788.  
  789.  
  790. kipit(p, ia, type, len)
  791.      struct pbuf *p;
  792.      long ia;
  793.      int type;
  794.      int len;
  795. {
  796.   register struct aaconf *m;
  797.   struct udp u;
  798.  
  799.   m = (struct aaconf *)(p->p_off + sizeof (struct ip) + sizeof u);
  800.   m->magic = aaMagic;
  801.   m->type = type;
  802.   m->flags = 0;
  803.   m->count = len;
  804.   m->ipaddr = conf.ipaddr;
  805.   u.src = u.dst = aaPort;
  806.   u.length = len + aaconfMinSize + sizeof u;
  807.   u.checksum = 0;
  808. #ifdef SNMP
  809.   mib_udp.udpOutDatagrams++;
  810. #endif
  811.   *(struct udp *)(p->p_off + sizeof (struct ip)) = u;
  812.   p->p_len = u.length + sizeof (struct ip);
  813.   setiphdr(p, ia);
  814.   routeip(p, 0, 0);
  815. }
  816.